package com.och.mrcp.core.sip.encoder;

import com.och.mrcp.core.sip.model.SipMessage;
import com.och.mrcp.core.sip.model.SipRequest;
import com.och.mrcp.core.sip.model.SipResponse;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

@Slf4j
public class SipMessageEncoder {
    
    public static String encode(SipMessage message) {
        try {
            if (message instanceof SipRequest) {
                return encodeRequest((SipRequest) message);
            } else if (message instanceof SipResponse) {
                return encodeResponse((SipResponse) message);
            } else {
                throw new IllegalArgumentException("Unknown message type: " + message.getClass());
            }
        } catch (Exception e) {
            log.error("Failed to encode SIP message: {}", e.getMessage(), e);
            throw new RuntimeException("SIP message encoding failed", e);
        }
    }
    
    private static String encodeRequest(SipRequest request) {
        StringBuilder sb = new StringBuilder();
        
        // Start line
        sb.append(request.getStartLine()).append("\r\n");
        
        // Required headers
        addRequiredHeaders(sb, request);
        
        // Optional headers
        addOptionalHeaders(sb, request);
        
        // Empty line
        sb.append("\r\n");
        
        // Body
        if (request.getBody() != null && !request.getBody().isEmpty()) {
            sb.append(request.getBody());
        }
        
        return sb.toString();
    }
    
    private static String encodeResponse(SipResponse response) {
        StringBuilder sb = new StringBuilder();
        
        // Start line
        sb.append(response.getStartLine()).append("\r\n");
        
        // Required headers
        addRequiredHeaders(sb, response);
        
        // Optional headers
        addOptionalHeaders(sb, response);
        
        // Empty line
        sb.append("\r\n");
        
        // Body
        if (response.getBody() != null && !response.getBody().isEmpty()) {
            sb.append(response.getBody());
        }
        
        return sb.toString();
    }
    
    private static void addRequiredHeaders(StringBuilder sb, SipMessage message) {
        // Via header
        if (message.getVia() != null) {
            sb.append("Via: ").append(message.getVia()).append("\r\n");
        }
        
        // From header
        if (message.getFrom() != null) {
            sb.append("From: ").append(message.getFrom()).append("\r\n");
        }
        
        // To header
        if (message.getTo() != null) {
            sb.append("To: ").append(message.getTo()).append("\r\n");
        }
        
        // Call-ID header
        if (message.getCallId() != null) {
            sb.append("Call-ID: ").append(message.getCallId()).append("\r\n");
        }
        
        // CSeq header
        if (message.getCseq() != null) {
            sb.append("CSeq: ").append(message.getCseq()).append("\r\n");
        }
    }
    
    private static void addOptionalHeaders(StringBuilder sb, SipMessage message) {
        // Contact header
        if (message.getContact() != null) {
            sb.append("Contact: ").append(message.getContact()).append("\r\n");
        }
        
        // Content-Type header
        if (message.getContentType() != null) {
            sb.append("Content-Type: ").append(message.getContentType()).append("\r\n");
        }
        
        // Content-Length header
        if (message.getBody() != null) {
            int contentLength = message.getBody().length();
            sb.append("Content-Length: ").append(contentLength).append("\r\n");
        }
        
        // Other custom headers
        for (Map.Entry<String, String> entry : message.getHeaders().entrySet()) {
            String name = entry.getKey();
            String value = entry.getValue();
            
            // Skip already added headers
            if (!isStandardHeader(name)) {
                sb.append(name).append(": ").append(value).append("\r\n");
            }
        }
    }
    
    private static boolean isStandardHeader(String headerName) {
        String lowerName = headerName.toLowerCase();
        return lowerName.equals("via") || 
               lowerName.equals("from") || 
               lowerName.equals("to") || 
               lowerName.equals("call-id") || 
               lowerName.equals("cseq") || 
               lowerName.equals("contact") || 
               lowerName.equals("content-type") || 
               lowerName.equals("content-length");
    }
}
